use std::collections::HashMap;
use std::str::FromStr;
use async_graphql::connection::{Connection, Edge, EmptyFields};
use async_graphql::Result as GraphQLResult;
use meilisearch_sdk::client::Client;
use sea_orm::{DatabaseConnection, EntityTrait, QueryFilter, ColumnTrait, QueryOrder, QuerySelect, TransactionTrait, Set, ActiveModelTrait};
use sea_orm::prelude::Decimal;
use sea_orm::sea_query::Keyword;
use snowid::SnowID;
use sqlx::types::chrono::Utc;
use tracing::info;
use crate::entity::product_main;
use crate::entity::product_specification;
use crate::graphql::product_graphql::{CreateProductInput, ProductConnection, ProductObject, ProductSpecificationObject, UpdateProductInput};


pub async fn query_products_with_cursor(
    db: &DatabaseConnection,
    meilisearch: &Client,
    keyword: String,
    cursor: Option<String>,
    limit: u32,
) -> GraphQLResult<ProductConnection> {
    // 使用 Meilisearch 进行全文搜索
    let index = meilisearch.index("products");

    // 构建搜索查询
    let mut search_query = {
        let mut query = index.search();
        if !keyword.is_empty() {
            info!("Searching with keyword: {}", keyword);
            query.with_query(&keyword);
        }
        query
    };

    // 设置分页参数
    let offset = if let Some(cursor) = cursor {
        cursor.parse::<usize>().unwrap_or(0)
    } else {
        0
    };

    let search_result = search_query
        .with_offset(offset)
        .with_limit(limit as usize)
        .execute::<serde_json::Value>()
        .await
        .map_err(|e| async_graphql::Error::new(format!("Meilisearch search failed: {}", e)))?;

    info!("Meilisearch returned {} hits", search_result.hits.len());
    // 提取搜索结果中的产品ID
    let product_ids: Vec<u64> = search_result
        .hits
        .iter()
        .filter_map(|hit| {
            // 首先尝试从 result 字段获取 ID
            if let Some(id_value) = hit.result.get("id") {
                match id_value {
                    serde_json::Value::String(id_str) => id_str.parse::<u64>().ok(),
                    serde_json::Value::Number(id_num) => id_num.as_u64(),
                    _ => None,
                }
            } else {
                // 如果 result 字段中没有 ID，尝试直接从 hit 中获取
                hit.formatted_result.as_ref()
                    .and_then(|formatted| formatted.get("id"))
                    .and_then(|id| id.as_str())
                    .and_then(|id_str| id_str.parse::<u64>().ok())
            }
        })
        .collect();
    info!("Extracted product IDs: {:?}", product_ids);
    if product_ids.is_empty() {
        return Ok(ProductConnection {
            products: vec![],
            has_next: false,
            next_cursor: None,
        });
    }

    // 根据搜索到的ID从数据库获取完整产品信息
    let products = product_main::Entity::find()
        .filter(product_main::Column::Id.is_in(product_ids))
        .order_by_asc(product_main::Column::Id)
        .all(db)
        .await?;

    // 获取产品规格
    let product_ids: Vec<u64> = products.iter().map(|p| p.id).collect();
    let specifications = if !product_ids.is_empty() {
        product_specification::Entity::find()
            .filter(product_specification::Column::ProductId.is_in(product_ids))
            .all(db)
            .await?
    } else {
        vec![]
    };

    let mut specs_by_product: HashMap<u64, Vec<product_specification::Model>> = HashMap::new();
    for spec in specifications {
        specs_by_product
            .entry(spec.product_id)
            .or_insert_with(Vec::new)
            .push(spec);
    }

    // 构建产品对象列表
    let mut product_objects = Vec::new();
    for product in products {
        let specifications = specs_by_product
            .remove(&product.id)
            .unwrap_or_default()
            .into_iter()
            .map(ProductSpecificationObject::from)
            .collect();

        let mut product_obj = ProductObject::from(product);
        product_obj.specifications = specifications;
        product_objects.push(product_obj);
    }

    // 判断是否有下一页
    let has_next_page = search_result.hits.len() > limit as usize;

    // 计算下一个游标
    let next_cursor = if has_next_page {
        Some((offset + limit as usize).to_string())
    } else {
        None
    };

    // 构建并返回 ProductConnection
    Ok(ProductConnection {
        products: product_objects,
        has_next: has_next_page,
        next_cursor,
    })
}

pub async fn get_products_with_cursor(
    db: &DatabaseConnection,
    cursor: Option<String>,
    limit: u32,
) -> GraphQLResult<ProductConnection> {

    // 解析游标
    let after_id = cursor.and_then(|a| Some(a.parse::<u64>().unwrap_or(0u64)));

    // 构建查询
    let mut query = product_main::Entity::find();

    // 应用游标过滤
    if let Some(after_id) = after_id {
        query = query.filter(product_main::Column::Id.gt(after_id));
    }

    // 执行查询
    query = query
        .order_by_asc(product_main::Column::Id)
        .limit(limit as u64 + 1); // 多获取一个元素以检查是否有下一页

    let products = query.all(db).await?;

    // 判断是否有下一页
    let has_next_page = products.len() > limit as usize;

    // 截取实际需要的数据
    let products: Vec<_> = if has_next_page {
        products[..limit as usize].to_vec()
    } else {
        products
    };

    // 获取产品规格
    let product_ids: Vec<u64> = products.iter().map(|p| p.id).collect();
    let specifications = if !product_ids.is_empty() {
        product_specification::Entity::find()
            .filter(product_specification::Column::ProductId.is_in(product_ids))
            .all(db)
            .await?
    } else {
        vec![]
    };

    let mut specs_by_product: HashMap<u64, Vec<product_specification::Model>> = HashMap::new();

    for spec in specifications {
        specs_by_product
            .entry(spec.product_id)
            .or_insert_with(Vec::new)
            .push(spec);
    }

    // 构建产品对象列表
    let mut product_objects = Vec::new();
    for product in products {
        let specifications = specs_by_product
            .remove(&product.id)
            .unwrap_or_default()
            .into_iter()
            .map(ProductSpecificationObject::from)
            .collect();

        let mut product_obj = ProductObject::from(product);
        product_obj.specifications = specifications;
        product_objects.push(product_obj);
    }

    // 计算下一个游标
    let next_cursor = if has_next_page {
        product_objects.last().map(|p| p.id.clone())
    } else {
        None
    };

    // 构建并返回 ProductConnection
    Ok(ProductConnection {
        products: product_objects,
        has_next: has_next_page,
        next_cursor,
    })
}

pub async fn get_product_by_id(
    db: &DatabaseConnection,
    product_id: String,
) -> GraphQLResult<Option<ProductObject>> {
    let product_id = product_id.parse::<u64>().map_err(|_| async_graphql::Error::new("Invalid product ID format"))?;
    // 查询产品主信息
    let product = product_main::Entity::find_by_id(product_id)
        .one(db)
        .await?;

    if let Some(product) = product {
        // 查询该产品的所有规格
        let specifications = product_specification::Entity::find()
            .filter(product_specification::Column::ProductId.eq(product_id))
            .all(db)
            .await?;

        let specifications = specifications.into_iter()
            .map(|spec| ProductSpecificationObject::from(spec))
            .collect();
        let mut product = ProductObject::from(product);
        product.specifications = specifications;

        Ok(Some(product))
    } else {
        Ok(None)
    }
}

pub async fn delete_product(
    db: &DatabaseConnection,
    meilisearch: &Client,
    product_id: String,
) -> GraphQLResult<bool> {
    // 开始事务
    let txn = db.begin().await?;

    let product_id = product_id.parse::<u64>().map_err(|_| async_graphql::Error::new("Invalid product ID format"))?;
    // 先删除关联的产品规格
    product_specification::Entity::delete_many()
        .filter(product_specification::Column::ProductId.eq(product_id))
        .exec(&txn)
        .await?;

    // 再删除产品主信息
    let result = product_main::Entity::delete_by_id(product_id)
        .exec(&txn)
        .await?;

    // 提交事务
    txn.commit().await?;


    // 从 Meilisearch 中删除文档
    let index = meilisearch.index("products");
    index.delete_document(product_id).await
        .map_err(|e| async_graphql::Error::new(format!("Failed to delete document from Meilisearch: {}", e)))?;


    // 返回是否成功删除（根据影响行数判断）
    Ok(result.rows_affected > 0)
}

pub async fn create_product(
    db: &DatabaseConnection,
    meilisearch: &Client,
    input: CreateProductInput,
) -> GraphQLResult<ProductObject> {
    // 开始事务
    let txn = db.begin().await?;
    let sn = SnowID::new(1)?;
    // 生成雪花ID
    let product_id = sn.generate();
    let now = Utc::now().naive_utc();

    let price = Decimal::from_str(&input.price)
        .map_err(|_| async_graphql::Error::new("Invalid price format"))?;


    // 创建产品主信息
    let product_model = product_main::ActiveModel {
        id: Set(product_id),
        title: Set(input.title.clone()),
        cover_addr: Set(input.cover_addr),
        description: Set(input.description.clone()),
        price: Set(price),
        rate: Set(input.rate.clone().parse()?),
        detail_addr: Set(input.detail_addr),
        stockpile: Set(input.stockpile),
        stockpile_frozen: Set(0), // 初始冻结库存为0
        status: Set(input.status),
        create_time: Set(now),
        update_time: Set(now),
    };

    let product = product_model.insert(&txn).await?;

    // 处理产品规格（如果有）
    let mut specifications = Vec::new();
    if let Some(spec_inputs) = input.specifications {
        for spec_input in spec_inputs {
            let spec_id = sn.generate();
            let spec_model = product_specification::ActiveModel {
                id: Set(spec_id),
                product_id: Set(product_id),
                item: Set(spec_input.item.clone()),
                value: Set(spec_input.value.clone()),
                create_time: Set(now),
                update_time: Set(now),
            };

            let spec = spec_model.insert(&txn).await?;
            specifications.push(ProductSpecificationObject::from(spec));
        }
    }

    // 提交事务
    txn.commit().await?;

    // 添加到 Meilisearch 索引
    let index = meilisearch.index("products");

    // 准备要添加到索引的数据
    let document = serde_json::json!({
        "id": product_id,
        "title": input.title,
        "description": input.description,
        "price": input.price,
        "rate": input.rate,
        "specifications": specifications.iter().map(|spec| {
            serde_json::json!({
                spec.item.clone(): spec.value.clone(),
            })
        }).collect::<Vec<_>>(),
    });

    // 添加文档到索引
    index.add_documents(&[document], Some("id")).await
        .map_err(|e| async_graphql::Error::new(format!("Failed to add document to Meilisearch: {}", e)))?;


    // 构造返回对象
    let mut product_obj = ProductObject::from(product);
    product_obj.specifications = specifications;

    Ok(product_obj)
}


pub async fn update_product(
    db: &DatabaseConnection,
    meilisearch: &Client,
    product_id: String,
    input: UpdateProductInput,
) -> GraphQLResult<ProductObject> {
    // 开始事务
    let txn = db.begin().await?;

    let product_id = product_id.parse::<u64>().map_err(|_| async_graphql::Error::new("Invalid product ID format"))?;
    
    // 检查产品是否存在
    let existing_product = product_main::Entity::find_by_id(product_id)
        .one(&txn)
        .await?
        .ok_or_else(|| async_graphql::Error::new("Product not found"))?;

    // 准备更新模型
    let now = Utc::now().naive_utc();
    let mut product_model: product_main::ActiveModel = existing_product.into();

    // 只更新提供的字段
    if let Some(title) = input.title {
        product_model.title = Set(title);
    }

    if let Some(cover_addr) = input.cover_addr {
        product_model.cover_addr = Set(cover_addr);
    }

    if let Some(description) = input.description {
        product_model.description = Set(description);
    }

    if let Some(price_str) = input.price {
        let price = Decimal::from_str(&price_str)
            .map_err(|_| async_graphql::Error::new("Invalid price format"))?;
        product_model.price = Set(price);
    }

    if let Some(rate) = input.rate {
        product_model.rate = Set(rate.parse()?);
    }

    if let Some(detail_addr) = input.detail_addr {
        product_model.detail_addr = Set(detail_addr);
    }

    if let Some(stockpile) = input.stockpile {
        product_model.stockpile = Set(stockpile);
    }

    if let Some(status) = input.status {
        product_model.status = Set(status);
    }

    // 更新时间字段
    product_model.update_time = Set(now);

    // 执行更新
    let updated_product = product_model.update(&txn).await?;

    // 处理产品规格更新（如果有提供）
    if let Some(spec_updates) = input.specifications {
        // 获取当前所有规格
        let current_specs = product_specification::Entity::find()
            .filter(product_specification::Column::ProductId.eq(product_id))
            .all(&txn)
            .await?;

        let mut existing_spec_ids: std::collections::HashSet<u64> = current_specs
            .iter()
            .map(|spec| spec.id)
            .collect();

        let sn = SnowID::new(1)?;

        // 处理每个规格更新
        for spec_input in spec_updates {
            if let Some(spec_id_str) = spec_input.id {
                // 如果提供了ID，则是更新现有规格或删除规格
                if let Ok(spec_id) = spec_id_str.parse::<u64>() {
                    if existing_spec_ids.contains(&spec_id) {
                        // 更新现有规格
                        let mut spec_model: product_specification::ActiveModel = product_specification::Entity::find_by_id(spec_id)
                            .one(&txn)
                            .await?
                            .ok_or_else(|| async_graphql::Error::new("Product specification not found"))?
                            .into();

                        spec_model.item = Set(spec_input.item);
                        spec_model.value = Set(spec_input.value);
                        spec_model.update_time = Set(now);

                        spec_model.update(&txn).await?;
                        existing_spec_ids.remove(&spec_id);
                    } else {
                        // ID不存在，创建新规格
                        let new_spec_id = sn.generate();
                        let spec_model = product_specification::ActiveModel {
                            id: Set(new_spec_id),
                            product_id: Set(product_id),
                            item: Set(spec_input.item),
                            value: Set(spec_input.value),
                            create_time: Set(now),
                            update_time: Set(now),
                        };
                        spec_model.insert(&txn).await?;
                    }
                }
            } else {
                // 没有提供ID，创建新规格
                let new_spec_id = sn.generate();
                let spec_model = product_specification::ActiveModel {
                    id: Set(new_spec_id),
                    product_id: Set(product_id),
                    item: Set(spec_input.item),
                    value: Set(spec_input.value),
                    create_time: Set(now),
                    update_time: Set(now),
                };
                spec_model.insert(&txn).await?;
            }
        }

        // 删除未被更新的规格（在更新列表中未提及的规格）
        for spec_id in existing_spec_ids {
            product_specification::Entity::delete_by_id(spec_id)
                .exec(&txn)
                .await?;
        }
    }

    // 获取最新的产品规格
    let specifications = product_specification::Entity::find()
        .filter(product_specification::Column::ProductId.eq(product_id))
        .all(&txn)
        .await?;

    let specifications: Vec<ProductSpecificationObject> = specifications
        .into_iter()
        .map(ProductSpecificationObject::from)
        .collect();

    // 提交事务
    txn.commit().await?;

    // 构造返回对象
    let mut product_obj = ProductObject::from(updated_product);
    product_obj.specifications = specifications;


    // 更新 Meilisearch 文档
    let index = meilisearch.index("products");

    // 准备要更新的文档数据
    let document = serde_json::json!({
        "id": product_id,
        "title": product_obj.title,
        "description": product_obj.description,
        "price": product_obj.price.to_string(),
        "rate": product_obj.rate.to_string(),
        "specifications": product_obj.specifications.iter().map(|spec| {
            serde_json::json!({
                spec.item.clone(): spec.value.clone(),
            })
        }).collect::<Vec<_>>(),
    });

    // 更新文档到索引
    index.add_documents(&[document], Some("id")).await
        .map_err(|e| async_graphql::Error::new(format!("Failed to update document in Meilisearch: {}", e)))?;



    Ok(product_obj)
}